﻿using IPort;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading;
using System.Net.Sockets;
using System.Windows.Forms;

namespace PortUdpClient
{
    public class PortUdpClient : IPort.ILogicPort
    {

        List<byte> DataCancle = new List<byte>();

        EventWaitHandle eventWaitHandler;

        /// <summary>
        /// 定义端口实例
        /// </summary>
        Socket _port = null;

        public PortUdpClient()
        {
           
        }


        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="threadSleepTime"></param>
        /// <param name="portOutTimeVal"></param>
        public PortUdpClient(string cfg)
        {
            this.Open(cfg);
        }

        EndPoint serverEndPoint = null;
        EndPoint remoteEndPoint = null;
        int serverPort = 0;
        /// <summary>
        /// 打开端口的操作
        /// </summary>
        /// <param name="portCfg"></param>
        public bool Open(string portCfg)
        {
            try
            {
                if (portCfg == null)
                {
                    this.IsOpen = false;
                    return false;
                }
                //192.168.2.1:5004;192.168.2.11:5004,,,,,
                string[] portparams = portCfg.Split(',');
                if (portparams.Length != 6)
                {
                    this.IsOpen = false;
                    return false;
                }
                this.PortName = portparams[0];
                this.PortArgs = portCfg;
                string[] args = portparams[0].Split(';');
                if (args.Length != 2) return false;
                string serverip = args[0];
                string remoteip = args[1];
                if (_port == null)
                    _port = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                this.IsOpen = false;
                if (string.IsNullOrEmpty(serverip)) return false;
                if (string.IsNullOrEmpty(remoteip)) return false;
                string[] serverargs = serverip.Split(':');
                if (serverargs != null && serverargs.Length == 2)
                {
                    IPAddress ipdir = null;
                    IPAddress.TryParse(serverargs[0], out ipdir);
                    int port = 3600;
                    int.TryParse(serverargs[1],out port);
                    serverEndPoint = new IPEndPoint(ipdir, port);
                    if (_port != null)
                    {
                        this._port.Bind(serverEndPoint);
                        _port.BeginReceiveFrom(_RecvieBuffer, 0, _RecvieBuffer.Length, SocketFlags.None, ref serverEndPoint, new AsyncCallback(this.EndRecvie), _port);
                    }
                }
                string[] remoteargs = remoteip.Split(':');
                if (remoteargs != null && remoteargs.Length == 2)
                {
                    IPAddress ipdir = null;
                    IPAddress.TryParse(remoteargs[0], out ipdir);
                    int port = 3600;
                    int.TryParse(remoteargs[1], out port);
                    remoteEndPoint = new IPEndPoint(ipdir, port);
                }
                this.IsOpen = true;
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }

        }
        byte[] _RecvieBuffer = new byte[1024];
       

        SocketError _Error = new SocketError();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="res"></param>
        void EndSend(IAsyncResult res)
        {
            try
            {
                this._port.EndSend(res);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="res"></param>
        void EndRecvie(IAsyncResult res)
        {
            try
            {
                Socket innerport = res.AsyncState as Socket;
                if (innerport == null) return;
                int count = innerport.EndReceive(res);
                if (count > 0)
                {
                    byte[] innlist = new byte[count];
                    Array.Copy(this._RecvieBuffer, 0, innlist, 0, innlist.Length);
                    //     IOHelper.DebugMsg.Log(this.PortName+"  Recvied Data :"+BitConverter.ToString(innlist));
                    if (this.OnPortData != null)
                    {
                        this.OnPortData(this.PortName, innlist);
                    }
                    else
                    {
                        lock (this.DataCancle)
                        {
                            this.DataCancle.AddRange(innlist);
                        }
                    }
                }
                if (_port != null)
                {
                    _port.BeginReceiveFrom(_RecvieBuffer, 0, _RecvieBuffer.Length, SocketFlags.None, ref serverEndPoint, new AsyncCallback(this.EndRecvie), _port);
                }
            }
            catch (Exception ex)
            {
                
            }
        }


        public bool Close(string args)
        {
            if (_port == null) return false;
            if (this.IsOpen) _port.Close();
            this.IsOpen = false;
            return true;
        }

        public byte[] ReadData()
        {
            lock (this.DataCancle)
            {
                byte[] buffer = this.DataCancle.ToArray();
                this.DataCancle.Clear();
                return buffer;
            }
        }

        public bool WriteData(byte[] buffer)
        {
            try
            {
                if (this._port == null) return false;
                if (!this.IsOpen) return false;
                //  IOHelper.DebugMsg.Log(this.PortName + "  Write Data :" + BitConverter.ToString(buffer));
                if (_port != null)
                {
                    this._port.BeginSendTo(buffer, 0, buffer.Length, SocketFlags.None, remoteEndPoint, new AsyncCallback(EndSend), this._port);
                }
                if (_Error != SocketError.Success)
                {
                    if (_Error == SocketError.ConnectionAborted)
                    {
                        this.IsOpen = false;
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                //mIOMannager.LogManager.LogHelper.WriteFile(this.Flag, ex.Message);
                return false;
            }
        }

        public byte[] ReadData(string portname)
        {
            throw new NotImplementedException();
        }

        public bool WriteData(string portname, byte[] buffer)
        {
            throw new NotImplementedException();
        }

        public event IPort.OnPortDataHandler OnPortData;

        string _PortName = string.Empty;

        public string PortName
        {
            get
            {
                return _PortName;
            }
            set
            {
                _PortName = value;
            }
        }

        string _portAegs = string.Empty;

        public string PortArgs
        {
            get
            {
                return _portAegs;
            }
            set
            {
                _portAegs = value;
            }
        }

        public int BytesCanRead
        {
            get { return this.DataCancle.Count; }
        }

        bool _IsOpen = false;

        public bool IsOpen
        {
            get { return _IsOpen; }
            set { _IsOpen = value; }
        }
    }
}
